package org.dim.main;

import org.dim.config.Bean;
import org.dim.config.Property;
import org.dim.config.parse.ConfigManager;
import org.dim.utils.BeanUtils;

import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Condition;

public class ClassPathXmlApplicationContext implements BeanFactory {
    Map<String, Bean>config;
    Map<String,Object>context=new HashMap<>();

    @Override
    public Object getBean(String beanName) {
       //根据bean的名称获得单例
        Object bean=context.get(beanName);
        return bean;
    }

    public ClassPathXmlApplicationContext(String path){
       config= ConfigManager.getConfig( path);
       if (config!=null){
           for (Map.Entry<String,Bean>en: config.entrySet()){
               String beanName=en.getKey();
               Bean bean=en.getValue();
               Object exitBean=context.get(beanName);
               if (exitBean==null){
                   Object beanObj=createBean(bean);
                   context.put(beanName,beanObj);
           }

           }
        }
    }
    private Object createBean(Bean bean) {
        //1.获得bean的class
        String className=bean.getClassName();
        Object beanObj=null;
        try {
            Class clazz=Class.forName(className);
            //2.获得bean的属性，将其注入
           beanObj=clazz.newInstance();  //newInstance调用的是空参构造，如果没有空参则报错
             //通过反射已成功实例化了一个对象。-----------------------------------------------------------------
            //获得bean，将其注入
            if (bean.getProperties()!=null){
                //值的注入
                for (Property prop:bean.getProperties()){

                       String name = prop.getName();
                    //根据名称调用set方法
                    Method setMethod= BeanUtils.getWriteMethod(beanObj,name);
                    Object param=null;
                    if (prop.getValue()!=null){
                        //简单注入--值的注入
                        String value=prop.getValue();

                        param=value;

                    }

                    if (prop.getRef()!=null){
                        //注入其他bean到当前bean。查找要注入的是否已创建/已在容器
                       Object exitBean=context.get(prop.getRef());
                       if (exitBean==null){
                           exitBean=createBean(config.get(prop.getRef()));
                           //将bean丢入容器
                           context.put(prop.getRef(),exitBean);
                       }
                       param=exitBean;
                    }
                    setMethod.invoke(beanObj,param);
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException("检查bean的class的配置: "+className);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw new RuntimeException("bean没有对应的set方法");
        }catch (Exception e){
            e.printStackTrace();
        }
       return beanObj;
    }
}
